package com.dongnaoedu.rpc.redis.spring;

import java.lang.reflect.Method;
import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Component;

import com.dongnaoedu.rpc.redis.annotation.RedisRpcEndpoint;
import com.dongnaoedu.rpc.redis.annotation.RedisRpcProducer;

/**
 * 增强
 * 
 * @author Tony
 *
 */
@Component
public class RedisRpcProcessor implements BeanPostProcessor {

	private final Log log = LogFactory.getLog(getClass());

	@Autowired
	RedisMessageListenerContainer redisMessageListenerContainer;

	@Autowired
	ProviderListener providerListener;

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// 判断是否被标注为redis-rpc服务提供者
		Class<? extends Object> clazz = bean.getClass();
		Class<?>[] interfaces = clazz.getInterfaces();
		if (clazz.isAnnotationPresent(RedisRpcProducer.class) && interfaces.length != 0) {
			Method[] methods = clazz.getMethods();
			for (Method method : methods) {
				if (method.isAnnotationPresent(RedisRpcEndpoint.class)) {
					String interfaceName = interfaces[0].getName();
					// 生成唯一实例ID
					String instanceId = UUID.randomUUID().toString();
					// channel命名规则：类名@方法名@实例ID
					String channel = "provider@" + interfaceName + "@" + method.getName() + "@" + instanceId;
					log.info("channelName: " + channel);
					// 监听指定的channel
					redisMessageListenerContainer.addMessageListener(new MessageListenerAdapter(providerListener),
							new ChannelTopic(channel));
				}
			}
		}
		return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
	}
}
